//
//  XiangQuBaseParser.m
//  XiangQu
//
//  Created by yandi on 14/10/25.
//  Copyright (c) 2014年 Qiuyin. All rights reserved.
//

#import "XiangQuBaseParser.h"

@interface XiangQuBaseParser ()

@property (nonatomic, strong) NSMutableDictionary *dictOfType;
@end

static char *keyArr;
@implementation XiangQuBaseParser

#pragma mark -init
- (instancetype)init {
    if (self = [super init]) {
        self.dictOfType = [NSMutableDictionary dictionary];
        
        NSMutableArray *keysArr = [NSMutableArray array];
        objc_setAssociatedObject(self, &keyArr, keysArr, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
        
        Class class = self.class;
        while (class != [XiangQuBaseParser class]) {
            unsigned int propertyCount;
            objc_property_t *properties = class_copyPropertyList(class, &propertyCount);
            for (unsigned int i = 0; i < propertyCount; i++) {
                objc_property_t property = properties[i];
                const char *nameOfProperty = property_getName(property);
                
                // strOfProperty
                NSString *strOfProperty = [NSString stringWithUTF8String:nameOfProperty];
                [keysArr addObject:strOfProperty];
                
                // attributeOfProperty
                const char *attributeOfProperty = property_getAttributes(property);
                NSString *strOfAttribute = [NSString stringWithUTF8String:attributeOfProperty];
                if ([strOfAttribute rangeOfString:@"&,N"].location != NSNotFound) {
                    NSArray *componentsOfArr = [strOfAttribute componentsSeparatedByString:@"\""];
                    
                    if ([strOfAttribute rangeOfString:@"NSArray"].location != NSNotFound || [strOfAttribute rangeOfString:@"NSMutableArray"].location != NSNotFound) {
                        NSString *strOfType = [componentsOfArr objectAtIndex:1];
                        strOfType = [strOfType stringByReplacingOccurrencesOfString:@"<" withString:@""];
                        strOfType = [strOfType stringByReplacingOccurrencesOfString:@">" withString:@""];
                        strOfType = [strOfType stringByReplacingOccurrencesOfString:@"NSMutableArray" withString:@""];
                        strOfType = [strOfType stringByReplacingOccurrencesOfString:@"NSArray" withString:@""];
                        [self.dictOfType setValue:strOfType forKey:strOfProperty];
                    } else {
                        [self.dictOfType setValue:[componentsOfArr objectAtIndex:1] forKey:strOfProperty];
                    }
                }
            }
            free(properties);
            class = [class superclass];
        }
    }
    return self;
}

#pragma mark -mapperKey
- (NSDictionary *)mapperKey {
    return @{};
}

#pragma mark -parserBody
- (void)parserBody:(NSDictionary *)parserDict {
    self.code = [[parserDict objectForKey:@"code"] description];
    if ([XiangQuTool isStringEmpty:self.code]) {
        self.code = [[parserDict objectForKey:@"errorCode"] description];
    }
    if ([self.code isEqualToString:@"200"]) {
        self.isSucceed = YES;
    }
    self.msg = [parserDict valueForKey:@"msg"];
    if ([XiangQuTool isStringEmpty:self.msg]) {
        self.msg = [parserDict valueForKey:@"moreInfo"];
    }
    [self recursionParser:parserDict instance:self];
}

#pragma mark -recursionParser
- (void)recursionParser:(NSDictionary *)parserDict instance:(XiangQuBaseParser *)instance {
    NSArray *keysArr = objc_getAssociatedObject(instance, &keyArr);
    for (NSString *key in keysArr) {
        NSString *replaceStrOfProperty = [[instance mapperKey] objectForKey:key];
        NSObject *parserObject;
        if (replaceStrOfProperty.length > 0) {
            parserObject = [parserDict objectForKey:replaceStrOfProperty];
        } else {
            parserObject = [parserDict objectForKey:key];
        }
        [self setValue:parserObject forKey:key instance:instance];
    }
}

#pragma mark - setValue
- (void)setValue:(NSObject *)value forKey:(NSString *)key instance:(XiangQuBaseParser *)instance {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
    if ([value isKindOfClass:[NSString class]] || [value isKindOfClass:[NSNumber class]]) {
        SEL setSelector = [[self class] constructSetSelectorWithKey:key];
        [instance performSelector:setSelector withObject:value.description];
    } else if ([value isKindOfClass:[NSDictionary class]]) {
        SEL setSelector = [[self class] constructSetSelectorWithKey:key];
        NSString *nameOfClass = [instance.dictOfType valueForKey:key];
        Class classOfSubInstance = NSClassFromString(nameOfClass);
        XiangQuBaseParser *subInstance = [[classOfSubInstance alloc] init];
        [instance performSelector:setSelector withObject:subInstance];
        [self recursionParser:(NSDictionary *)value instance:subInstance];
    } else if ([value isKindOfClass:[NSArray class]]) {
        SEL setSelector = [[self class] constructSetSelectorWithKey:key];
        NSMutableArray *arrOfData = [NSMutableArray array];
        [instance performSelector:setSelector withObject:arrOfData];
        
        Class classOfSubInstance = NSClassFromString([instance.dictOfType valueForKey:key]);
        if (classOfSubInstance) {
            for (NSDictionary *parserDict in (NSArray *)value) {
                XiangQuBaseParser *subInstance = [[classOfSubInstance alloc] init];
                [arrOfData addObject:subInstance];
                [self recursionParser:parserDict instance:subInstance];
            }
        } else {
            for (NSObject *objValue in (NSArray *)value) {
                if ([objValue isKindOfClass:[NSString class]] || [objValue isKindOfClass:[NSNumber class]]) {
                    [arrOfData addObject:objValue.description];
                }
            }
        }
    }
#pragma clang diagnostic pop
}

#pragma mark -constructSelector
+ (SEL)constructSetSelectorWithKey:(NSString *)key {
    NSString *keyOfSelector = [NSString stringWithFormat:@"set%@%@:",[key substringToIndex:1].uppercaseString,[key substringFromIndex:1]];
    SEL setSelector = NSSelectorFromString(keyOfSelector);
    return setSelector;
}

@end
